#pragma once 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <iostream>

#include "Connect.hpp"
#include "Tool.hpp"
using namespace std;


struct Myself 
{
    string name_;
    string school_;
    string passwd_;
    uint32_t my_id_;
};
class ChatClient
{
    public:
        ChatClient(const string& ip)
        {
            ip_ = ip;
            tcp_sock_ = -1;
            udp_sock_ = -1;
            vec_.clear();
        }
        ~ChatClient()
        {

        }
        
        //创建tcp套接字
        int Create_tcp()
        {
            tcp_sock_ = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(tcp_sock_ < 0)
            {
                return -1;
            }
            return 0;
        }
       
        //创建udp套接字
        int Create_udp()
        {
            udp_sock_ = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
            if(udp_sock_ < 0)
            {
                return -1;
            }
            return 0;
        }
        //连接tcp套接字
        int ConnectoSer()
        {
            struct sockaddr_in dest_addr;
            dest_addr.sin_family = AF_INET;
            dest_addr.sin_port = htons(TCP_PORT); 
            dest_addr.sin_addr.s_addr = inet_addr(ip_.c_str());
            int ret = connect(tcp_sock_,(struct sockaddr*)&dest_addr,sizeof(dest_addr));
            if(ret < 0)
            {
                close(tcp_sock_);
                return -1;
            }
            return 0;
        }
        
        //注册具体的信息
        int RegisterInfo()
        {
            //创建套接字
            int ret = Create_tcp();
            if(ret < 0)
            {
                LOG(ERROR,"create_tcp faild") << endl;
                return -1;
            }
            //连接服务器
            ret = ConnectoSer();
            if(ret < 0)
            {
                LOG(ERROR,"connectoser faild") << endl;
                return -2;
            }
            //第一个发送的是一个字节的数据包
            char type = Register;
            ssize_t send_size = send(tcp_sock_,&type,1,0);
            if(send_size < 0)
            {
                close(tcp_sock_);
                return -3;
            }
            //传送数据包注册信息
            struct RegisterInfo ri;
            cout << "please input name:";
            fflush(stdout);
            cin >> ri.name_;
            me_.name_ = ri.name_;
            cout << "please input school:";
            fflush(stdout);
            cin >> ri.school_;
            me_.school_ = ri.school_;
            while(1)
            {
                string first,second;
                cout << "please input passwd:";
                fflush(stdout);
                cin >> first;
                cout << "please input passwd again:";
                fflush(stdout);
                cin >> second;
                if(first == second)
                {
                    strncpy(ri.passwd_,first.c_str(),sizeof(ri.passwd_));
                    me_.passwd_ = first;
                    break;
                }
            }
                send_size = send(tcp_sock_,&ri,sizeof(ri),0);
                if(send_size < 0)
                {
                     LOG(INFO,"send_second faild");      
                }

            //发送成功
            LOG(INFO,"register info success") << endl;

            //接收应答
            struct ReplyInfo reply_info;
            
            ssize_t recv_size = recv(tcp_sock_,&reply_info,sizeof(reply_info),0);
            if(recv_size < 0)
            {
                LOG(ERROR,"recv faild") << endl; 
                close(tcp_sock_);
                return -1;
            }
            else if(recv_size == 0)
            {
                LOG(ERROR,"dest port shutdown") << endl;
                close(tcp_sock_);
                return -2;
            }
            //接收到了
            if(reply_info.resp_status_ == REGISTER_FAILED)
            {
                LOG(ERROR,"recv register_faild") << endl;
                close(tcp_sock_);
                return -3;
            }
            //注册成功
            me_.my_id_ = reply_info.id_;
            LOG(INFO,"Register success") << endl ;
           cout << "me_.my_id_:" << me_.my_id_ << endl;
           cout << "me_.passwd_:"<< me_.passwd_ << endl;
           cout << "me_name_" << me_.name_ << endl;
        }

        void CloseFd()
        {
            if(tcp_sock_ > 0)
            {
                close(tcp_sock_);
                tcp_sock_ = -1;
            }
        }

        int LoginInfo()
        {
           //创建套接字
           int ret = Create_tcp();
           if(ret < 0)
           {
               LOG(ERROR,"create_tcp to login faild") << endl;
               return -1;
           }
           //连接服务器
           ret = ConnectoSer();
           if(ret < 0)
           {
                LOG(ERROR,"connect to server of login faild") << endl;
                return -1;
           }

           //发送登录的信息
           //发送类型
           char type = Login;
           ssize_t send_size = send(tcp_sock_,&type,1,0);
           if(send_size < 0)
           {
               LOG(ERROR,"login send to server faild") << endl;
               return -1;
           }
           LOG(INFO,"type send success") << endl;
           //发送登录包
           struct LoginInfo li;
           li.id_ = me_.my_id_;
           strncpy(li.passwd_,me_.passwd_.c_str(),sizeof(li.passwd_));
           send_size = send(tcp_sock_,&li,sizeof(li),0);
           if(send_size < 0)
           {
                LOG(ERROR,"login send info faild") << endl;
                return -1;
           }
           LOG(INFO,"send login info success") << endl;
           //接收应答
           struct ReplyInfo ri;
           ssize_t recv_size = recv(tcp_sock_,&ri,sizeof(ri),0);
           if(recv_size < 0)
           {
               LOG(ERROR,"login recv faild") << endl;
               return -1;
           }
           else if(recv_size == 0)
           {
               LOG(ERROR,"dest port shutdown --login") << endl;
               close(tcp_sock_);
               return -1;
           }
           if(ri.resp_status_ != LOGIN_SUCCESS)
           {
               LOG(ERROR,"login faild") << endl;
               return -1;
           }
           LOG(INFO,"login success") << endl;
           return 0;

        }
        int SendMsg(string& msg)
        {
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(UDP_PORT);
            addr.sin_addr.s_addr = inet_addr(ip_.c_str());
            ssize_t send_size = sendto(udp_sock_,msg.c_str(),msg.size(),0,(struct sockaddr*)&addr,sizeof(addr));
            if(send_size < 0)
            {
                LOG(ERROR,"sendto faild") << endl;
                return -1;
            }
            return 0;
        }
        
        int RecvMsg(string* msg)
        {
            char buf[UDP_DATA_MAX_LEN] = {0};

            ssize_t recv_size = recvfrom(udp_sock_,buf,sizeof(buf)-1,0,NULL,NULL);
            if(recv_size < 0)
            {
                LOG(ERROR,"recv_size faild") << endl;
                return -1;
            }
            msg->assign(buf,strlen(buf));
            return 0;
        }
        Myself& GetMe()
        {
            return me_;
        }
        vector<UdpMsg>& GetVec()
        {
            return vec_;
        }
    private:
        int tcp_sock_;
        string ip_;
        int udp_sock_;
        struct Myself me_;
        vector<UdpMsg> vec_;
};
